package com.gec.anan.payment.service.impl;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.gec.anan.common.constant.MqConst;
import com.gec.anan.common.execption.AnanException;
import com.gec.anan.common.result.Result;
import com.gec.anan.common.result.ResultCodeEnum;
import com.gec.anan.common.service.RabbitService;
import com.gec.anan.common.util.RequestUtils;
import com.gec.anan.driver.client.DriverAccountFeignClient;
import com.gec.anan.model.entity.payment.PaymentInfo;
import com.gec.anan.model.enums.TradeType;
import com.gec.anan.model.form.driver.TransferForm;
import com.gec.anan.model.form.payment.PaymentInfoForm;
import com.gec.anan.model.vo.order.OrderRewardVo;
import com.gec.anan.model.vo.payment.WxPrepayVo;
import com.gec.anan.order.client.OrderInfoFeignClient;
import com.gec.anan.payment.config.WxPayV3Properties;
import com.gec.anan.payment.mapper.PaymentInfoMapper;
import com.gec.anan.payment.service.WxPayService;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.service.payments.jsapi.JsapiService;
import com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension;
import com.wechat.pay.java.service.payments.jsapi.model.*;
import com.wechat.pay.java.service.payments.model.Transaction;
import io.seata.spring.annotation.GlobalTransactional;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.jce.provider.AnnotatedException;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;

@Service
@Slf4j
public class WxPayServiceImpl implements WxPayService {
    @Autowired
    private RabbitService rabbitService;

    @Autowired
    private PaymentInfoMapper paymentInfoMapper;

    @Autowired
    private RSAAutoCertificateConfig rsaAutoCertificateConfig;
    @Autowired
    private WxPayV3Properties wxPayV3Properties;

    //微信支付
    @Override
    public WxPrepayVo createJsapi(PaymentInfoForm paymentInfoForm) {
        try {
            //1.添加支付的记（数据库）
            LambdaQueryWrapper<PaymentInfo> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(PaymentInfo::getOrderNo, paymentInfoForm.getOrderNo());
            PaymentInfo paymentInfo = paymentInfoMapper.selectOne(queryWrapper);
            if(paymentInfo==null){
                //没有则新建一个
                paymentInfo = new PaymentInfo();
                paymentInfo.setPaymentStatus(0);//0表示未支付
                BeanUtils.copyProperties(paymentInfoForm, paymentInfo);
                paymentInfoMapper.insert(paymentInfo);
            }

            //2.创建微信支付适用对象
            JsapiServiceExtension service = new JsapiServiceExtension.Builder().config(rsaAutoCertificateConfig).build();

            //3.设置微信规定的支付参数
            PrepayRequest request = new PrepayRequest();
            Amount amount = new Amount();
            amount.setTotal(paymentInfoForm.getAmount().multiply(new BigDecimal(100)).intValue());
            request.setAmount(amount);
            request.setAppid(wxPayV3Properties.getAppid());
            request.setMchid(wxPayV3Properties.getMerchantId());
            //string[1,127]
            String description = paymentInfo.getContent();
            if(description.length() > 127) {
                description = description.substring(0, 127);
            }
            request.setDescription(paymentInfo.getContent());
            request.setNotifyUrl(wxPayV3Properties.getNotifyUrl());
            request.setOutTradeNo(paymentInfo.getOrderNo());

            //获取用户信息
            Payer payer = new Payer();
            payer.setOpenid(paymentInfoForm.getCustomerOpenId());
            request.setPayer(payer);

            //是否指定分账，不指定不能分账
            SettleInfo settleInfo = new SettleInfo();
            settleInfo.setProfitSharing(true);
            request.setSettleInfo(settleInfo);
            //4.发起调用
            PrepayWithRequestPaymentResponse response = service.prepayWithRequestPayment(request);

            //5.返回对象
            WxPrepayVo wxPrepayVo = new WxPrepayVo();
            BeanUtils.copyProperties(paymentInfoForm, wxPrepayVo);
            wxPrepayVo.setTimeStamp(response.getTimeStamp());
            return wxPrepayVo;

        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    //微信支付异步通知的api
    @Transactional
    @Override
    //写法比较固定，微信提供
    public void wxnotify(HttpServletRequest request) {
        //1.回调通知的验签与解密
        //从request头信息获取参数
        //HTTP 头 Wechatpay-Signature
        // HTTP 头 Wechatpay-Nonce
        //HTTP 头 Wechatpay-Timestamp
        //HTTP 头 Wechatpay-Serial
        //HTTP 头 Wechatpay-Signature-Type
        //HTTP 请求体 body。切记使用原始报文，不要用 JSON 对象序列化后的字符串，避免验签的 body 和原文不一致。
        String wechatPaySerial = request.getHeader("Wechatpay-Serial");
        String nonce = request.getHeader("Wechatpay-Nonce");
        String timestamp = request.getHeader("Wechatpay-Timestamp");
        String signature = request.getHeader("Wechatpay-Signature");
        String requestBody = RequestUtils.readData(request);
        log.info("wechatPaySerial：{}", wechatPaySerial);
        log.info("nonce：{}", nonce);
        log.info("timestamp：{}", timestamp);
        log.info("signature：{}", signature);
        log.info("requestBody：{}", requestBody);

        //2.构造 RequestParam
        RequestParam requestParam = new RequestParam.Builder()
                .serialNumber(wechatPaySerial)
                .nonce(nonce)
                .signature(signature)
                .timestamp(timestamp)
                .body(requestBody)
                .build();


        //3.初始化 NotificationParser
        NotificationParser parser = new NotificationParser(rsaAutoCertificateConfig);
        //4.以支付通知回调为例，验签、解密并转换成 Transaction
        Transaction transaction = parser.parse(requestParam, Transaction.class);
        log.info("成功解析：{}", JSON.toJSONString(transaction));
        if(null != transaction && transaction.getTradeState() == Transaction.TradeStateEnum.SUCCESS) {
            //5.处理支付业务
            this.handlePayment(transaction);
        }
    }

    //查询支付状态
    @Override
    public Boolean queryPayStatus(String orderNo) {
        //1.微信支付操作对象
        JsapiServiceExtension service = new JsapiServiceExtension.Builder().config(rsaAutoCertificateConfig).build();

        //2.封装查询对象
        QueryOrderByOutTradeNoRequest request = new QueryOrderByOutTradeNoRequest();
        request.setMchid(wxPayV3Properties.getMerchantId());
        request.setOutTradeNo(orderNo);

        //3.调用操作对象的方法实现
        Transaction transaction = service.queryOrderByOutTradeNo(request);

        //4.查询返回的状态
        if(transaction!=null&&transaction.getTradeState()== Transaction.TradeStateEnum.SUCCESS){
            this.handlePayment(transaction);
            return true;
        }
        return false;
    }

    @Autowired
    private OrderInfoFeignClient orderInfoFeignClient;
    @Autowired
    private DriverAccountFeignClient driverAccountFeignClient;

    @GlobalTransactional
    @Override
    public void handleOrder(String orderNo) {
        //1.更新订单状态
        orderInfoFeignClient.updateOrderPayStatus(orderNo);
        //2.系统奖励
        OrderRewardVo orderRewardVo = orderInfoFeignClient.getOrderRewardFee(orderNo).getData();
        if(orderRewardVo!=null&&orderRewardVo.getRewardFee().doubleValue()>0){
            TransferForm transferForm = new TransferForm();
            transferForm.setTradeNo(orderNo);
            transferForm.setTradeType(TradeType.REWARD.getType());
            transferForm.setContent(TradeType.REWARD.getContent());
            transferForm.setAmount(orderRewardVo.getRewardFee());
            transferForm.setDriverId(orderRewardVo.getDriverId());
            driverAccountFeignClient.transfer(transferForm);
        }
    }

    private void handlePayment(Transaction transaction) {
        //1.更新订单的支付状态
        String orderNo = transaction.getOutTradeNo();
        LambdaQueryWrapper<PaymentInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(PaymentInfo::getOrderNo, orderNo);
        PaymentInfo paymentInfo = paymentInfoMapper.selectOne(queryWrapper);
        if(paymentInfo.getPaymentStatus()==1){
            return;
        }
        paymentInfo.setPaymentStatus(1);
        paymentInfo.setOrderNo(orderNo);
        paymentInfo.setTransactionId(transaction.getTransactionId());
        paymentInfo.setCallbackContent(JSON.toJSONString(transaction));
        paymentInfo.setCallbackTime(new Date());
        paymentInfoMapper.updateById(paymentInfo);

        //2.发送mq
        rabbitService.sendMessage(MqConst.EXCHANGE_ORDER,
                MqConst.ROUTING_PAY_SUCCESS,
                orderNo);
    }
}
